From 7086b5730be9ed931d84444e694ed84ae35a4628 Mon Sep 17 00:00:00 2001 From: "smh22@firebug.cl.cam.ac.uk" Date: Tue, 29 Nov 2005 14:50:30 +0100 Subject: [PATCH] Cleanup backend block device logic under save/restore; this should fix the issues some people have seen with segfaults in vbd_translate and/or user-space hangs. Signed-off-by: Steven Hand --- .../drivers/xen/blkback/common.h | 8 +++++++- .../drivers/xen/blkback/interface.c | 4 +++- .../drivers/xen/blkback/xenbus.c | 19 +++++++++++++++++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index bd22c40332..96eafda2fe 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -38,6 +38,8 @@ struct vbd { struct block_device *bdev; }; +struct backend_info; + typedef struct blkif_st { /* Unique identifier for this interface. */ domid_t domid; @@ -48,8 +50,10 @@ typedef struct blkif_st { /* Comms information. */ blkif_back_ring_t blk_ring; struct vm_struct *blk_ring_area; - /* VBDs attached to this interface. */ + /* The VBD attached to this interface. */ struct vbd vbd; + /* Back pointer to the backend_info. */ + struct backend_info *be; /* Private fields. */ enum { DISCONNECTED, CONNECTED } status; #ifdef CONFIG_XEN_BLKDEV_TAP_BE @@ -103,6 +107,8 @@ void blkif_xenbus_init(void); irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs); +void update_blkif_status(blkif_t *blkif); + #endif /* __BLKIF__BACKEND__COMMON_H__ */ /* diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c index fd8eccec8d..900b482719 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -112,7 +112,9 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) blkif->irq = bind_evtchn_to_irqhandler( blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); - blkif->status = CONNECTED; + + /* We're potentially connected now */ + update_blkif_status(blkif); return 0; } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index b119efa697..a5a3113e44 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -50,6 +50,16 @@ static void backend_changed(struct xenbus_watch *, const char **, unsigned int); +void update_blkif_status(blkif_t *blkif) +{ + if(blkif->irq && blkif->vbd.bdev) { + blkif->status = CONNECTED; + (void)blkif_be_int(0, blkif, NULL); + } + maybe_connect(blkif->be); +} + + static ssize_t show_physical_device(struct device *_dev, char *buf) { struct xenbus_device *dev = to_xenbus_device(_dev); @@ -81,6 +91,7 @@ static int blkback_remove(struct xenbus_device *dev) be->backend_watch.node = NULL; } if (be->blkif) { + be->blkif->status = DISCONNECTED; blkif_put(be->blkif); be->blkif = NULL; } @@ -123,6 +134,9 @@ static int blkback_probe(struct xenbus_device *dev, goto fail; } + /* setup back pointer */ + be->blkif->be = be; + err = xenbus_watch_path2(dev, dev->nodename, "physical-device", &be->backend_watch, backend_changed); if (err) @@ -209,7 +223,8 @@ static void backend_changed(struct xenbus_watch *watch, device_create_file(&dev->dev, &dev_attr_physical_device); device_create_file(&dev->dev, &dev_attr_mode); - maybe_connect(be); + /* We're potentially connected now */ + update_blkif_status(be->blkif); } } @@ -235,7 +250,7 @@ static void frontend_changed(struct xenbus_device *dev, if (err) { return; } - maybe_connect(be); + update_blkif_status(be->blkif); break; case XenbusStateClosing: -- 2.30.2